// 消息路由模块：将客户端的信息转发给所有在线用户

#pragma once
#include <iostream>
#include <vector>
#include "InetAddr.hpp"
#include "Log.hpp"
using namespace LogModule;

class Route
{
private:
    bool IsExit(InetAddr &addr)
    {
        for (auto &e : _online_user)
        {
            if (e == addr)
                return true;
        }
        return false;
    }

    void AddUesr(InetAddr &addr)
    {
        _online_user.push_back(addr);
        LOG(LogLevel::INFO) << "用户：" << addr.Getname() << "登录";
    }

    void DeleteUser(InetAddr &addr)
    {
        for (auto it = _online_user.begin(); it < _online_user.end(); it++)
        {
            if (addr == *it)
            {
                // erase参数只能是迭代器
                _online_user.erase(it);
                LOG(LogLevel::INFO) << "用户" << it->Getname() << "退出登录";
            }
        }
    }

public:
    void MessageRoute(int sockfd, std::string &message, InetAddr &addr)
    {
        // 加锁:在多线程下，可能出现多个客服端同时调用该函数进行登录、发送信息、退出登录等操作
        // 此时_online_user为临界资源，为了保证线程安全，加锁！
        LockGuard lockguard(_mutex);

        // 判断当前用户是否在，在线用户中
        if (!IsExit(addr))
        {
            // 没在，则添加
            AddUesr(addr);
        }

        // 当前用户一定在
        // 将当前用户的消息转发给所有人，包括自己
        for (auto &user : _online_user)
        {
            sendto(sockfd, message.c_str(), message.size(), 0, (const struct sockaddr *)&user, sizeof(user));
        }

        // 输入QUIT，表示用户退出
        if (message == "QUIT")
        {
            DeleteUser(addr);
        }
    }

private:
    // 首次发消息，视为登录
    std::vector<InetAddr> _online_user;
    Mutex _mutex;
};